home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 008a / perl40_2.zip / FORM.C < prev    next >
C/C++ Source or Header  |  1991-11-28  |  10KB  |  404 lines

  1. /* $RCSfile: form.c,v $$Revision: 4.0.1.2 $$Date: 91/11/05 17:18:43 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    form.c,v $
  9.  * Revision 4.0.1.2  91/11/05  17:18:43  lwall
  10.  * patch11: formats didn't fill their fields as well as they could
  11.  * patch11: ^ fields chopped hyphens on line break
  12.  * patch11: # fields could write outside allocated memory
  13.  *
  14.  * Revision 4.0.1.1  91/06/07  11:07:59  lwall
  15.  * patch4: new copyright notice
  16.  * patch4: default top-of-form format is now FILEHANDLE_TOP
  17.  *
  18.  * Revision 4.0  91/03/20  01:19:23  lwall
  19.  * 4.0 baseline.
  20.  *
  21.  */
  22.  
  23.  
  24. #include "EXTERN.h"
  25. #include "perl.h"
  26.  
  27.  
  28. /* Forms stuff */
  29.  
  30.  
  31. void
  32. form_parseargs(fcmd)
  33. register FCMD *fcmd;
  34. {
  35.     register int i;
  36.     register ARG *arg;
  37.     register int items;
  38.     STR *str;
  39.     ARG *parselist();
  40.     line_t oldline = curcmd->c_line;
  41.     int oldsave = savestack->ary_fill;
  42.  
  43.  
  44.     str = fcmd->f_unparsed;
  45.     curcmd->c_line = fcmd->f_line;
  46.     fcmd->f_unparsed = Nullstr;
  47.     (void)savehptr(&curstash);
  48.     curstash = str->str_u.str_hash;
  49.     arg = parselist(str);
  50.     restorelist(oldsave);
  51.  
  52.  
  53.     items = arg->arg_len - 1;    /* ignore $$ on end */
  54.     for (i = 1; i <= items; i++) {
  55.     if (!fcmd || fcmd->f_type == F_NULL)
  56.         fatal("Too many field values");
  57.     dehoist(arg,i);
  58.     fcmd->f_expr = make_op(O_ITEM,1,
  59.       arg[i].arg_ptr.arg_arg,Nullarg,Nullarg);
  60.     if (fcmd->f_flags & FC_CHOP) {
  61.         if ((fcmd->f_expr[1].arg_type & A_MASK) == A_STAB)
  62.         fcmd->f_expr[1].arg_type = A_LVAL;
  63.         else if ((fcmd->f_expr[1].arg_type & A_MASK) == A_EXPR)
  64.         fcmd->f_expr[1].arg_type = A_LEXPR;
  65.         else
  66.         fatal("^ field requires scalar lvalue");
  67.     }
  68.     fcmd = fcmd->f_next;
  69.     }
  70.     if (fcmd && fcmd->f_type)
  71.     fatal("Not enough field values");
  72.     curcmd->c_line = oldline;
  73.     Safefree(arg);
  74.     str_free(str);
  75. }
  76.  
  77.  
  78. int newsize;
  79.  
  80.  
  81. #define CHKLEN(allow) \
  82. newsize = (d - orec->o_str) + (allow); \
  83. if (newsize >= curlen) { \
  84.     curlen = d - orec->o_str; \
  85.     GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
  86.     d = orec->o_str + curlen;    /* in case it moves */ \
  87.     curlen = orec->o_len - 2; \
  88. }
  89.  
  90.  
  91. format(orec,fcmd,sp)
  92. register struct outrec *orec;
  93. register FCMD *fcmd;
  94. int sp;
  95. {
  96.     register char *d = orec->o_str;
  97.     register char *s;
  98.     register int curlen = orec->o_len - 2;
  99.     register int size;
  100.     FCMD *nextfcmd;
  101.     FCMD *linebeg = fcmd;
  102.     char tmpchar;
  103.     char *t;
  104.     CMD mycmd;
  105.     STR *str;
  106.     char *chophere;
  107.  
  108.  
  109.     mycmd.c_type = C_NULL;
  110.     orec->o_lines = 0;
  111.     for (; fcmd; fcmd = nextfcmd) {
  112.     nextfcmd = fcmd->f_next;
  113.     CHKLEN(fcmd->f_presize);
  114.     /*SUPPRESS 560*/
  115.     if (s = fcmd->f_pre) {
  116.         while (*s) {
  117.         if (*s == '\n') {
  118.             while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
  119.             d--;
  120.             if (fcmd->f_flags & FC_NOBLANK) {
  121.             if (d == orec->o_str || d[-1] == '\n') {
  122.                 orec->o_lines--;    /* don't print blank line */
  123.                 linebeg = fcmd->f_next;
  124.                 break;
  125.             }
  126.             else if (fcmd->f_flags & FC_REPEAT)
  127.                 nextfcmd = linebeg;
  128.             else
  129.                 linebeg = fcmd->f_next;
  130.             }
  131.             else
  132.             linebeg = fcmd->f_next;
  133.         }
  134.         *d++ = *s++;
  135.         }
  136.     }
  137.     if (fcmd->f_unparsed)
  138.         form_parseargs(fcmd);
  139.     switch (fcmd->f_type) {
  140.     case F_NULL:
  141.         orec->o_lines++;
  142.         break;
  143.     case F_LEFT:
  144.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  145.         str = stack->ary_array[sp+1];
  146.         s = str_get(str);
  147.         size = fcmd->f_size;
  148.         CHKLEN(size);
  149.         chophere = Nullch;
  150.         while (size && *s && *s != '\n') {
  151.         if (*s == '\t')
  152.             *s = ' ';
  153.         size--;
  154.         if (*s && index(chopset,(*d++ = *s++)))
  155.             chophere = s;
  156.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  157.             *s = ' ';
  158.         }
  159.         if (size || !*s)
  160.         chophere = s;
  161.         else if (chophere && chophere < s && *s && index(chopset,*s))
  162.         chophere = s;
  163.         if (fcmd->f_flags & FC_CHOP) {
  164.         if (!chophere)
  165.             chophere = s;
  166.         size += (s - chophere);
  167.         d -= (s - chophere);
  168.         if (fcmd->f_flags & FC_MORE &&
  169.           *chophere && strNE(chophere,"\n")) {
  170.             while (size < 3) {
  171.             d--;
  172.             size++;
  173.             }
  174.             while (d[-1] == ' ' && size < fcmd->f_size) {
  175.             d--;
  176.             size++;
  177.             }
  178.             *d++ = '.';
  179.             *d++ = '.';
  180.             *d++ = '.';
  181.             size -= 3;
  182.         }
  183.         while (*chophere && index(chopset,*chophere)
  184.           && isSPACE(*chophere))
  185.             chophere++;
  186.         str_chop(str,chophere);
  187.         }
  188.         if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  189.         size = 0;            /* no spaces before newline */
  190.         while (size) {
  191.         size--;
  192.         *d++ = ' ';
  193.         }
  194.         break;
  195.     case F_RIGHT:
  196.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  197.         str = stack->ary_array[sp+1];
  198.         t = s = str_get(str);
  199.         size = fcmd->f_size;
  200.         CHKLEN(size);
  201.         chophere = Nullch;
  202.         while (size && *s && *s != '\n') {
  203.         if (*s == '\t')
  204.             *s = ' ';
  205.         size--;
  206.         if (*s && index(chopset,*s++))
  207.             chophere = s;
  208.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  209.             *s = ' ';
  210.         }
  211.         if (size || !*s)
  212.         chophere = s;
  213.         else if (chophere && chophere < s && *s && index(chopset,*s))
  214.         chophere = s;
  215.         if (fcmd->f_flags & FC_CHOP) {
  216.         if (!chophere)
  217.             chophere = s;
  218.         size += (s - chophere);
  219.         s = chophere;
  220.         while (*chophere && index(chopset,*chophere)
  221.           && isSPACE(*chophere))
  222.             chophere++;
  223.         }
  224.         tmpchar = *s;
  225.         *s = '\0';
  226.         while (size) {
  227.         size--;
  228.         *d++ = ' ';
  229.         }
  230.         size = s - t;
  231.         (void)bcopy(t,d,size);
  232.         d += size;
  233.         *s = tmpchar;
  234.         if (fcmd->f_flags & FC_CHOP)
  235.         str_chop(str,chophere);
  236.         break;
  237.     case F_CENTER: {
  238.         int halfsize;
  239.  
  240.  
  241.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  242.         str = stack->ary_array[sp+1];
  243.         t = s = str_get(str);
  244.         size = fcmd->f_size;
  245.         CHKLEN(size);
  246.         chophere = Nullch;
  247.         while (size && *s && *s != '\n') {
  248.         if (*s == '\t')
  249.             *s = ' ';
  250.         size--;
  251.         if (*s && index(chopset,*s++))
  252.             chophere = s;
  253.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  254.             *s = ' ';
  255.         }
  256.         if (size || !*s)
  257.         chophere = s;
  258.         else if (chophere && chophere < s && *s && index(chopset,*s))
  259.         chophere = s;
  260.         if (fcmd->f_flags & FC_CHOP) {
  261.         if (!chophere)
  262.             chophere = s;
  263.         size += (s - chophere);
  264.         s = chophere;
  265.         while (*chophere && index(chopset,*chophere)
  266.           && isSPACE(*chophere))
  267.             chophere++;
  268.         }
  269.         tmpchar = *s;
  270.         *s = '\0';
  271.         halfsize = size / 2;
  272.         while (size > halfsize) {
  273.         size--;
  274.         *d++ = ' ';
  275.         }
  276.         size = s - t;
  277.         (void)bcopy(t,d,size);
  278.         d += size;
  279.         *s = tmpchar;
  280.         if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  281.         size = 0;            /* no spaces before newline */
  282.         else
  283.         size = halfsize;
  284.         while (size) {
  285.         size--;
  286.         *d++ = ' ';
  287.         }
  288.         if (fcmd->f_flags & FC_CHOP)
  289.         str_chop(str,chophere);
  290.         break;
  291.     }
  292.     case F_LINES:
  293.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  294.         str = stack->ary_array[sp+1];
  295.         s = str_get(str);
  296.         size = str_len(str);
  297.         CHKLEN(size+1);
  298.         orec->o_lines += countlines(s,size) - 1;
  299.         (void)bcopy(s,d,size);
  300.         d += size;
  301.         if (size && s[size-1] != '\n') {
  302.         *d++ = '\n';
  303.         orec->o_lines++;
  304.         }
  305.         linebeg = fcmd->f_next;
  306.         break;
  307.     case F_DECIMAL: {
  308.         double value;
  309.  
  310.  
  311.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  312.         str = stack->ary_array[sp+1];
  313.         size = fcmd->f_size;
  314.         CHKLEN(size+1);
  315.         /* If the field is marked with ^ and the value is undefined,
  316.            blank it out. */
  317.         if ((fcmd->f_flags & FC_CHOP) && !str->str_pok && !str->str_nok) {
  318.         while (size) {
  319.             size--;
  320.             *d++ = ' ';
  321.         }
  322.         break;
  323.         }
  324.         value = str_gnum(str);
  325.         if (fcmd->f_flags & FC_DP) {
  326.         sprintf(d, "%#*.*f", size, fcmd->f_decimals, value);
  327.         } else {
  328.         sprintf(d, "%*.0f", size, value);
  329.         }
  330.         d += size;
  331.         break;
  332.     }
  333.     }
  334.     }
  335.     CHKLEN(1);
  336.     *d++ = '\0';
  337. }
  338.  
  339.  
  340. countlines(s,size)
  341. register char *s;
  342. register int size;
  343. {
  344.     register int count = 0;
  345.  
  346.  
  347.     while (size--) {
  348.     if (*s++ == '\n')
  349.         count++;
  350.     }
  351.     return count;
  352. }
  353.  
  354.  
  355. do_write(orec,stab,sp)
  356. struct outrec *orec;
  357. STAB *stab;
  358. int sp;
  359. {
  360.     register STIO *stio = stab_io(stab);
  361.     FILE *ofp = stio->ofp;
  362.  
  363.  
  364. #ifdef DEBUGGING
  365.     if (debug & 256)
  366.     fprintf(stderr,"left=%ld, todo=%ld\n",
  367.       (long)stio->lines_left, (long)orec->o_lines);
  368. #endif
  369.     if (stio->lines_left < orec->o_lines) {
  370.     if (!stio->top_stab) {
  371.         STAB *topstab;
  372.         char tmpbuf[256];
  373.  
  374.  
  375.         if (!stio->top_name) {
  376.         if (!stio->fmt_name)
  377.             stio->fmt_name = savestr(stab_name(stab));
  378.         sprintf(tmpbuf, "%s_TOP", stio->fmt_name);
  379.         topstab = stabent(tmpbuf,FALSE);
  380.         if (topstab && stab_form(topstab))
  381.             stio->top_name = savestr(tmpbuf);
  382.         else
  383.             stio->top_name = savestr("top");
  384.         }
  385.         topstab = stabent(stio->top_name,FALSE);
  386.         if (!topstab || !stab_form(topstab)) {
  387.         stio->lines_left = 100000000;
  388.         goto forget_top;
  389.         }
  390.         stio->top_stab = topstab;
  391.     }
  392.     if (stio->lines_left >= 0 && stio->page > 0)
  393.         (void)putc('\f',ofp);
  394.     stio->lines_left = stio->page_len;
  395.     stio->page++;
  396.     format(&toprec,stab_form(stio->top_stab),sp);
  397.     fputs(toprec.o_str,ofp);
  398.     stio->lines_left -= toprec.o_lines;
  399.     }
  400.   forget_top:
  401.     fputs(orec->o_str,ofp);
  402.     stio->lines_left -= orec->o_lines;
  403. }
  404.